package com.origin.netlibrary.interceptor

import android.util.Log
import com.origin.netlibrary.NetUtils
import com.origin.netlibrary.bean.BaseResponse
import com.origin.utils.MD5Utils
import com.origin.utils.SharedPreferencesUtils
import com.origin.utils.gson.GsonUtils.strToJavaBean
import com.origin.utils.gson.GsonUtils.toJsonString
import com.origin.utils.log.LogUtils
import okhttp3.*
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.io.IOException
import java.lang.Exception
import java.nio.charset.Charset
import java.util.*

class NetInterceptor private constructor() : Interceptor {

    // val myself = getExternalFilesDir("myself")
    private val LINE =
        "============================================================================"

    companion object {
        private val instance: NetInterceptor by lazy { NetInterceptor() }
        fun init(): NetInterceptor {
            return instance
        }
    }


    override fun intercept(chain: Interceptor.Chain): Response {

        var callChain = "方法调用链：\n"
        Thread.currentThread().stackTrace.forEach {
            callChain += "${it.toString()} \n"
        }

        //这个chain里面包含了request和response，所以你要什么都可以从这里拿
        val request = chain.request()

        var allStr = "";
        val requestUrl = request.url().toString();
        allStr += "url  ${requestUrl}\n";

        var headersStr = "请求头： \n${LINE} \n"
        // 请求头
        request.headers().names().forEach {

            val s = "$it : ${request.header(it)}\n"
            headersStr += s

        }
        headersStr += "$LINE \n"
        allStr += headersStr
        val buffer: okio.Buffer = okio.Buffer()
        var parameterStr = ""
        request.body()?.let {

            it.writeTo(buffer)
            it

        }?.contentType()?.charset(Charset.forName("UTF-8"))
            ?.apply {
                val requestParameter = buffer.readString(this)
                allStr += "请求参数： \n${LINE} \n"
                if (requestParameter.length < 293460) {
                    requestParameter.split('&').forEach {
                        try {
                            val s = it.split('=')
                            parameterStr += " ${s[0]}:${s[1]} " + "\n"
                        } catch (e: Exception) {
                            parameterStr = ""
                            Log.e("内容长度 ", "length  " + requestParameter.length)
                            parameterStr += requestParameter + "\n"


                        }

                    }
                }

                allStr += parameterStr
                allStr += "$LINE\n\n\n"
            }
        buffer.clear()


        try {
            val t1 = System.nanoTime() //请求发起的时间
            Log.e("OfflineCacheInterceptor", "yyy")
            val response = chain.proceed(request)

            Log.e("OfflineCacheInterceptor", "zzz")

            val t2 = System.nanoTime() //收到响应的时间
            allStr += "接收响应: \n${LINE} \n"
            allStr += "响应 code [${response.code()}]\n"
            allStr += "请求时长 ${(t2 - t1) / 1e6}ms\n"
            allStr += "响应头 \n"
            val headers = response.headers()
            allStr += "$headers \n"

            allStr += "响应结果 \n"

            val responseBody = response.peekBody((1024 * 1024).toLong())
            val json: String = responseBody.string()
            val formatJson = formatJson(json)
            allStr += formatJson

//            saveOffline(response, headers, responseBody, json, requestUrl, parameterStr, headersStr)
            LogUtils.json(allStr)

            return response;
        } catch (e: Exception) {
            Log.e("异常", "ex " + e.toString())
            return getOffline(e, requestUrl, parameterStr, headersStr)

        }


    }

    private fun saveOffline(
        response: Response,
        headers: Headers,
        responseBody: ResponseBody,
        json: String,
        requestUrl: String,
        parameterStr: String,
        headersStr: String
    ) {
        val baseResponse = BaseResponse();
        baseResponse.code = response.code()
        var i = 0
        val size: Int = headers.size()
        while (i < size) {
            val name = headers.name(i);
            val value = headers.value(i);
            baseResponse.headerMap[name] = value
            i++
        }
        baseResponse.message = response.message()
        baseResponse.protocol = response.protocol()
        baseResponse.mediaType = responseBody.contentType().toString()
        baseResponse.formatJson = json
        SharedPreferencesUtils.setParam(
            NetUtils.getApplication(),
            getUrlParameter(requestUrl, parameterStr, headersStr),
            baseResponse.toJsonString()
        )
    }

    private fun getOffline(
        e: Exception,
        requestUrl: String,
        parameterStr: String,
        headersStr: String
    ): Response {
        var baseResponseStr: String = SharedPreferencesUtils.getParam(
            NetUtils.getApplication(),
            getUrlParameter(requestUrl, parameterStr, headersStr), ""
        ) as String
        if (baseResponseStr.isEmpty()) {
            baseResponseStr =
                "{\"code\":200,\"formatJson\":\"\",\"headerMap\":{},\"mediaType\":\"application/json\",\"message\":\"\",\"protocol\":\"HTTP_1_1\"}"
            if (e is IOException) {
                baseResponseStr = "{\"code\":230,\"formatJson\":\"\",\"headerMap\":{},\"mediaType\":\"application/json\",\"message\":\"主动取消网络请求\",\"protocol\":\"HTTP_1_1\"}"
            }
        }
        LogUtils._e(e.toString() + "  getOffline $baseResponseStr")
        val baseResponse = baseResponseStr.strToJavaBean(BaseResponse::class.java)
        val headers = Response.Builder()
        headers.code(baseResponse.code)
        baseResponse.headerMap.forEach {
            headers.addHeader(it.key, it.value)
        }
        val responseBody =
            ResponseBody.create(
                MediaType.get(baseResponse.mediaType),
                baseResponse.formatJson
            )
        headers.body(responseBody)

        headers.request(
            Request.Builder()
                .url(requestUrl).build()
        )
        headers.protocol(baseResponse.protocol)
        headers.message(baseResponse.message)
        return headers
            .build()
    }

    private fun getUrlParameter(url: String, parameterStr: String, headersStr: String): String {
        return MD5Utils.md5(url + parameterStr + headersStr)
    }

    /**
     * @param json 格式化json字符串
     * @return
     */
    private fun formatJson(_json: String): String {
        var json = _json
        //        Log.e("TAG", "formatJson: >>" + json);
        try {
            if (json.startsWith("{")) {
                json = JSONObject(json).toString(4)
            } else if (json.startsWith("[")) {
                json = JSONArray(json).toString(4)
            }
        } catch (e: JSONException) {
            e.printStackTrace()
        }

        return json
    }
}